import { Inject, Provide } from "@midwayjs/core";
import { InjectEntityModel } from "@midwayjs/typeorm";
import { Repository } from "typeorm";
import { BblPrize } from "../entity/prize.entity";
import { BblAttach } from "../entity/attach.entity";
import { BblPrizeGroup } from "../entity/prize.group.entity";
import {
  PrizeCreateDto,
  PrizeListQueryDto,
  PrizePageQueryDto,
  PrizeListDto,
  PrizeInfoDto,
  PrizeUpdateDto,
  PrizeWeightUpdateDto
} from "../dto/prize.dto";

import { Utils } from "../utils";

@Provide()
export class PrizeService {
  @InjectEntityModel(BblPrize)
  prizeRepo: Repository<BblPrize>;

  @InjectEntityModel(BblAttach)
  attachRepo: Repository<BblAttach>;

  @InjectEntityModel(BblPrizeGroup)
  prizeGroupRepo: Repository<BblPrizeGroup>;

  @Inject()
  utils: Utils;

  /**
   * 创建奖品
   */
  async createPrize(dto: PrizeCreateDto): Promise<PrizeInfoDto> {
    const prize = this.prizeRepo.create({
      id: this.utils.snowFlake.generate(),
      prizeName: dto.prizeName,
      prizeDesc: dto.prizeDesc,
      prizeType: dto.prizeType,
      prizeQuantity: dto.prizeQuantity,
      remainingQuantity: dto.prizeQuantity,
      sortOrder: dto.sortOrder ?? 0,
      weight: dto.weight ?? 0, // 新增
      isDeleted: 0
    });

    if (dto.prizeImgId) {
      const prizeImage = await this.attachRepo.findOne({
        where: {
          attId: dto.prizeImgId
        }
      });
      if (prizeImage) {
        prize.prizeImage = prizeImage;
      }
    }

    // 设置奖品组关联
    if (dto.groupId) {
      const prizeGroup = await this.prizeGroupRepo.findOne({
        where: {
          id: dto.groupId
        }
      });
      if (prizeGroup) {
        prize.prizeGroup = prizeGroup;
      }
    }

    const saved = await this.prizeRepo.save(prize);

    // 将临时文件转换为正式文件
    if (saved.prizeImage) {
      saved.prizeImage.attState = "1";
      await this.attachRepo.save(saved.prizeImage);
    }

    return new PrizeInfoDto(saved);
  }

  /**
   * 奖品列表（不分页）
   */
  async list(query: PrizeListQueryDto): Promise<PrizeListDto[]> {
    const qb = this.prizeRepo
      .createQueryBuilder("prize")
      .leftJoinAndSelect("prize.prizeImage", "attach")
      .leftJoinAndSelect("prize.prizeGroup", "group")
      .where("prize.isDeleted = 0");

    if (query.prizeName) {
      qb.andWhere("prize.prizeName like :name", {
        name: `%${query.prizeName}%`
      });
    }
    if (query.prizeType) {
      qb.andWhere("prize.prizeType = :type", { type: query.prizeType });
    }
    if (query.groupId) {
      qb.andWhere("group.id = :groupId", { groupId: query.groupId });
    }

    const list = await qb
      .orderBy("prize.sortOrder", "ASC")
      .addOrderBy("prize.createdAt", "DESC")
      .getMany();

    return list.map((item) => new PrizeListDto(item));
  }

  /**
   * 奖品分页列表
   */
  async page(query: PrizePageQueryDto): Promise<{
    total: number;
    list: PrizeListDto[];
    pageSize: number;
    current: number;
  }> {
    const qb = this.prizeRepo
      .createQueryBuilder("prize")
      .leftJoinAndSelect("prize.prizeImage", "attach")
      .leftJoinAndSelect("prize.prizeGroup", "group")
      .where("prize.isDeleted = 0");

    if (query.prizeName) {
      qb.andWhere("prize.prizeName like :name", {
        name: `%${query.prizeName}%`
      });
    }
    if (query.prizeType) {
      qb.andWhere("prize.prizeType = :type", { type: query.prizeType });
    }
    if (query.groupId) {
      qb.andWhere("group.id = :groupId", { groupId: query.groupId });
    }

    const pageSize = parseInt(query.pageSize, 10) || 10;
    const current = parseInt(query.current, 10) || 1;

    const [list, total] = await qb
      .orderBy("prize.sortOrder", "ASC")
      .addOrderBy("prize.createdAt", "DESC")
      .skip((current - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    return {
      total,
      list: list.map((item) => new PrizeListDto(item)),
      pageSize: query.pageSize ? parseInt(query.pageSize, 10) : 10,
      current: query.current ? parseInt(query.current, 10) : 1
    };
  }

  /**
   * 奖品详情
   */
  async info(id: string): Promise<PrizeInfoDto | null> {
    const prize = await this.prizeRepo.findOne({
      where: { id, isDeleted: 0 },
      relations: ["prizeImage", "prizeGroup"]
    });
    return prize ? new PrizeInfoDto(prize) : null;
  }

  /**
   * 更新奖品
   */
  async update(id: string, dto: PrizeUpdateDto): Promise<boolean> {
    const prize = await this.prizeRepo.findOne({ where: { id, isDeleted: 0 } });
    if (!prize) return false;

    if (dto.prizeName !== undefined) prize.prizeName = dto.prizeName;
    if (dto.prizeDesc !== undefined) prize.prizeDesc = dto.prizeDesc;
    if (dto.prizeType !== undefined) prize.prizeType = dto.prizeType;
    if (dto.prizeQuantity !== undefined) {
      const diff = dto.prizeQuantity - prize.prizeQuantity;
      prize.prizeQuantity = dto.prizeQuantity;
      prize.remainingQuantity += diff;
      if (prize.remainingQuantity < 0) prize.remainingQuantity = 0;
    }
    if (dto.sortOrder !== undefined) prize.sortOrder = dto.sortOrder;
    if (dto.weight !== undefined) prize.weight = dto.weight; // 新增
    if (dto.prizeImgId !== undefined) {
      prize.prizeImage = dto.prizeImgId
        ? await this.attachRepo.findOne({
            where: { attId: dto.prizeImgId }
          })
        : null;
    }

    // 更新奖品组关联
    if (dto.groupId !== undefined) {
      prize.prizeGroup = dto.groupId
        ? await this.prizeGroupRepo.findOne({
            where: { id: dto.groupId }
          })
        : null;
    }

    await this.prizeRepo.save(prize);
    return true;
  }

  /**
   * 删除奖品（软删除）
   */
  async remove(id: string): Promise<boolean> {
    const prize = await this.prizeRepo.findOne({ where: { id, isDeleted: 0 } });
    if (!prize) return false;
    prize.isDeleted = 1;
    await this.prizeRepo.save(prize);
    return true;
  }

  /**
   * 批量更新奖品权重
   * @param dto 包含 groupId 和 weight 映射的对象
   * @returns 是否全部奖品都归属于 groupId 并已更新
   */
  async batchUpdatePrizeListWeight(dto: PrizeWeightUpdateDto) {
    const prizeIds = Object.keys(dto.weight);
    if (prizeIds.length === 0) {
      return {
        success: true,
        data: []
      };
    }
    const prizes = await this.prizeRepo.find({
      where: prizeIds.map((id) => ({ id })),
      relations: ["prizeGroup"]
    });
    // 判断所有奖品是否都归属于 groupId
    if (
      prizes.length !== prizeIds.length ||
      prizes.some((p) => !p.prizeGroup || p.prizeGroup.id !== dto.groupId)
    ) {
      return {
        success: false,
        data: []
      };
    }
    // 全部归属，批量更新权重
    for (const prize of prizes) {
      prize.weight = dto.weight[prize.id] ?? 0;
    }
    const saved = await this.prizeRepo.save(prizes);
    return {
      success: saved.length === prizeIds.length,
      data: saved.map((d) => new PrizeInfoDto(d))
    };
  }
}
